import java.net.*;

import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import java.awt.event.InputEvent;
import java.io.*;
public class StartPoint {
	
	/*Version 0.6. GetPortStatus and SetPOrtReset realisation*/
	
// ---------------------------- Internal methods -----------------------------------------//
	private static void ClearParsedCommand(String[] ParsedCommand )
	{
		for (int i = 0; i< ParsedCommand.length; i++)
		ParsedCommand[i] = "";
	}
	
	private static void PrintDebug (String[] Command )
	{
		System.out.println("============== Command recieved: ===================");
		for (int i = 0; i< Command.length; i++) System.out.print(Command[i]+ " ");
		System.out.println();
	}
//========================== End Internal methods =======================================//
	
	public static void main(String[] args) throws IOException {

// -------------------------------Initializing--------------------------------------------//
		BufferedReader in = null;
		PrintWriter out = null;
		ServerSocket Server = null;
		Socket Client = null;
		
		
		CommandParser CP = new CommandParser();
		String[] ParsedCommand;
		
		IncomingDataParser AcceptDataChecker = new IncomingDataParser();
		
		TelnetHandler SessionHandler = new TelnetHandler();
		String ServerReply;
		
		MA5600TelnetTransmissionController MA5600 = new MA5600TelnetTransmissionController();
		S2300TelnetTransmissionController S2300 = new S2300TelnetTransmissionController();
		E3528TelnetTransmissionController E3528 = new E3528TelnetTransmissionController();
		BRASTelnetTransmissionController BRAS = new BRASTelnetTransmissionController();
		
		// Getting today's date
		Locale local = new Locale("ru","RU");
		
		// Formatting the date to be represented in DAY.MONTH.YEAR
		DateFormat df = DateFormat.getDateInstance(DateFormat.DEFAULT, local); 
		Date currentDate = new Date(); 
		
		// Creating new log file and log directory if it Doesn't exist
		//File logFile = new File("C:\\Log\\" + df.format(currentDate) + ".log");
		File logFile = new File(df.format(currentDate) + ".log");
		
		// Initializing Logger class 
		Logger logger = new Logger();
		logger.NewLogEntry(false, "============================" + currentDate.toString() + "============================\n", logFile);
		
		//Defining if we also wish to duplicate output to screen, not just to log file 
		boolean DoubleLogToScreen = true;
		
		
		
// ============================ End Initializing =========================================//


// -------------------------------- Socket operating ------------------------------------//		
		// Launching Server socket
		try
		{
			logger.NewLogEntry(DoubleLogToScreen, "Launching server...\n", logFile);
			Server = new ServerSocket(15641);
		} catch (IOException e) 
		{
			logger.NewLogEntry(DoubleLogToScreen, "Unable to start server.", logFile);
			System.exit(-1);
		}
		
		// Waiting for connections
		while (true)
		{
		try
		{
			logger.NewLogEntry(DoubleLogToScreen, "Waiting for client...", logFile);
			Client = Server.accept();
			logger.NewLogEntry(false, "============================" + new Date().toString() + "============================\n", logFile);
			// This should be helpful for handling stuck sessions
			Client.setSoTimeout(3000);
			logger.NewLogEntry(DoubleLogToScreen, "The client IP-address is: " + Client.getInetAddress().toString(), logFile);
			logger.NewLogEntry(DoubleLogToScreen, "The client Port is: " + Client.getLocalPort(), logFile);			
			logger.NewLogEntry(DoubleLogToScreen, "Client has connected...", logFile);
		} 
		catch (Exception e)
		{
			logger.NewLogEntry(DoubleLogToScreen, "Unable to accept client.", logFile);
			e.printStackTrace();
		}
		
		try {
			in = new BufferedReader(new InputStreamReader(Client.getInputStream()));
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {
			out = new PrintWriter(Client.getOutputStream(), true);
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		String input; // The command accepted from socket
		logger.NewLogEntry(DoubleLogToScreen, "Waiting for messages...", logFile);
		
		try
		{
		while((input = in.readLine()) != null)
		{
			if (input.equalsIgnoreCase("exit")) break;
			
			// Extracting debug information
			logger.NewLogEntry(DoubleLogToScreen, "Command that came from socket: " + input, logFile);
			System.out.println(input);
			
			//Parsing the command from socket to ParsedCommand array
			ParsedCommand = CP.ParseInputFromSocket(input);
			
			// Let's see how the incoming command has been parsed
			logger.NewLogEntry(DoubleLogToScreen, "How the command has been parsed:", logFile);
			for (int i = 0; i<ParsedCommand.length; i++) logger.NewLogEntry(DoubleLogToScreen, ("[" + ParsedCommand[i] + "] "), logFile);
			
			logger.NewLogEntry(DoubleLogToScreen, "Server.isBound: " + Server.isBound() + "\n\n\n", logFile);
			
			// This piece of code checks the validity of device name for server socket
			if (! AcceptDataChecker.CheckDeviceValidity(ParsedCommand[0]).contentEquals("True"))
			{
				logger.NewLogEntry(DoubleLogToScreen, "Rejected by invalid device constaint: " + ParsedCommand[0], logFile);
				out.println("The device type " + ParsedCommand[0] + " is invalid\n\n");
				SessionHandler.disconnect();
				Client.close();
				input = "";
				ClearParsedCommand(ParsedCommand);
			}
			
			// This piece of code checks the validity of Command name for server socket
			if (! AcceptDataChecker.CheckCommandValidity(ParsedCommand[1]).contentEquals("True"))
			{
				logger.NewLogEntry(DoubleLogToScreen, "Rejected by invalid Command constaint: " + ParsedCommand[1], logFile);
				out.println("The Command " + ParsedCommand[1] + " is not valid\n\n");
				SessionHandler.disconnect();
				Client.close();
				input = "";
				ClearParsedCommand(ParsedCommand);
			}
			
			// This piece of code checks the validity of IP address for server socket
			if (! AcceptDataChecker.CheckIPValidity(ParsedCommand[2]).contentEquals("True"))
			{
				logger.NewLogEntry(DoubleLogToScreen, "Rejected by invalid IP address: " + ParsedCommand[2], logFile);
				out.println(AcceptDataChecker.CheckIPValidity(ParsedCommand[2])+ "\n\n");
				SessionHandler.disconnect();
				Client.close();
				input = "";
				ClearParsedCommand(ParsedCommand);
			}
			
			// The next piece of code is created for correct sending requests to BRAS
			if (ParsedCommand[0].contentEquals("BRAS"))
			{
				if (SessionHandler.ServerConnect("172.16.0.81", ParsedCommand[0]))
				{
					if (ParsedCommand[0].contentEquals("BRAS")) // Else if the command is for EdgeCore 3528, we have to launch appropriate Command Generator
					{
						if (ParsedCommand[1].contentEquals("GetUserAuth"))
						{
							try
							{
								ServerReply = SessionHandler.AdvancedSendCommandSequence("BRAS", "GetUserAuth", BRAS.CreateCommand(ParsedCommand));
								PrintDebug(ParsedCommand);
								logger.NewLogEntry(DoubleLogToScreen, ">>> The server has replied: <<<" + '\n' + ServerReply, logFile);
								out.println(ServerReply);
								SessionHandler.disconnect();
								input = "";
							}
							catch (Exception e)
							{
								e.printStackTrace();
							}
						}
					}
				}
				if (SessionHandler.ServerConnect("172.16.0.83", ParsedCommand[0]))
				{
					if (ParsedCommand[0].contentEquals("BRAS")) // Else if the command is for EdgeCore 3528, we have to launch appropriate Command Generator
					{
						if (ParsedCommand[1].contentEquals("GetUserAuth"))
						{
							try
							{
								ServerReply = SessionHandler.AdvancedSendCommandSequence("BRAS", "GetUserAuth", BRAS.CreateCommand(ParsedCommand));
								PrintDebug(ParsedCommand);
								logger.NewLogEntry(DoubleLogToScreen, ">>> The server has replied: <<<" + '\n' + ServerReply, logFile);
								out.println(ServerReply+"\n\n");
								SessionHandler.disconnect();
								Client.close();
								input = "";
								ClearParsedCommand(ParsedCommand);
							}
							catch (Exception e)
							{
								e.printStackTrace();
							}
						}
					}
				}
			}
			// This piece of code serves all other equipment
			if (SessionHandler.ServerConnect(ParsedCommand[2], ParsedCommand[0])) // Let't try to connect the server listed in command from socket
			{
				if (ParsedCommand[0].contentEquals("5600")) // If the command is for MA5600, we have to launch appropriate Command Generator
				{
					if (ParsedCommand[1].contentEquals("GetPortStatus"))
					{
						try
						{
							ServerReply = SessionHandler.AdvancedSendCommandSequence("5600", "GetPortStatus", MA5600.CreateCommand(ParsedCommand));
							PrintDebug(ParsedCommand);
							logger.NewLogEntry(DoubleLogToScreen, ">>> The server has replied: <<<" + '\n' + ServerReply, logFile);
							out.println(ServerReply+"\n\n");
							SessionHandler.disconnect();
							Client.close();
							input = "";
							ClearParsedCommand(ParsedCommand);
						}
						catch (Exception e)
						{
							e.printStackTrace();
						}
					}
					if (ParsedCommand[1].contentEquals("GetPortPVC"))
					{
						try
						{
							ServerReply = SessionHandler.AdvancedSendCommandSequence("5600", "GetPortPVC", MA5600.CreateCommand(ParsedCommand));
							PrintDebug(ParsedCommand);
							logger.NewLogEntry(DoubleLogToScreen, ">>> The server has replied: <<<" + '\n' + ServerReply, logFile);
							out.println(ServerReply+"\n\n");
							SessionHandler.disconnect();
							Client.close();
							input = "";
							ClearParsedCommand(ParsedCommand);
						}
						catch (Exception e)
						{
							e.printStackTrace();
						}
					}
					if (ParsedCommand[1].contentEquals("SetPortRateProfile") && ParsedCommand[4] != "")
					{
						try
						{
							ServerReply = SessionHandler.AdvancedSendCommandSequence("5600", "SetPortRateProfile", MA5600.CreateCommand(ParsedCommand));
							PrintDebug(ParsedCommand);
							logger.NewLogEntry(DoubleLogToScreen, ">>> The server has replied: <<<" + '\n' + ServerReply, logFile);
							out.println(ServerReply+"\n\n");
							SessionHandler.disconnect();
							Client.close();
							input = "";
							ClearParsedCommand(ParsedCommand);
						}
						catch (Exception e)
						{
							e.printStackTrace();
						}
					}
					if (ParsedCommand[1].contentEquals("SetPortReset"))
					{
						try
						{
							ServerReply = SessionHandler.AdvancedSendCommandSequence("5600", "SetPortReset", MA5600.CreateCommand(ParsedCommand));
							PrintDebug(ParsedCommand);
							logger.NewLogEntry(DoubleLogToScreen,">>> The server has replied: <<<" + '\n' + ServerReply, logFile);
							out.println(ServerReply+"\n\n");
							SessionHandler.disconnect();
							Client.close();
							input = "";
							ClearParsedCommand(ParsedCommand);
						}
						catch (Exception e)
						{
							e.printStackTrace();
						}
					}
					
				}
				else if (ParsedCommand[0].contentEquals("2300")) // Else if the command is for Quidway S2300, we have to launch appropriate Command Generator
				{
					if (ParsedCommand[1].contentEquals("GetPortStatus"))
					{
						try
						{
							ServerReply = SessionHandler.AdvancedSendCommandSequence("2300", "GetPortStatus", S2300.CreateCommand(ParsedCommand));
							PrintDebug(ParsedCommand);
							logger.NewLogEntry(DoubleLogToScreen, "==============The server has replied:=============" + '\n' + ServerReply, logFile);
							out.println(ServerReply+"\n\n");
							SessionHandler.disconnect();
							Client.close();
							input = "";
							ClearParsedCommand(ParsedCommand);
						}
						catch (Exception e)
						{
							e.printStackTrace();
						}
					}
					if (ParsedCommand[1].contentEquals("SetPortReset"))
					{
						try
						{
							ServerReply = SessionHandler.AdvancedSendCommandSequence("2300", "SetPortReset", S2300.CreateCommand(ParsedCommand));
							PrintDebug(ParsedCommand);
							logger.NewLogEntry(DoubleLogToScreen, ">>> The server has replied: <<<" + '\n' + ServerReply, logFile);
							out.println(ServerReply+"\n\n");
							SessionHandler.disconnect();
							Client.close();
							input = "";
							ClearParsedCommand(ParsedCommand);
						}
						catch (Exception e)
						{
							e.printStackTrace();
						}
					}
				}
				else if (ParsedCommand[0].contentEquals("3528")) // Else if the command is for EdgeCore 3528, we have to launch appropriate Command Generator
				{
					if (ParsedCommand[1].contentEquals("GetPortStatus"))
					{
						try
						{
							ServerReply = SessionHandler.AdvancedSendCommandSequence("3528", "GetPortStatus", E3528.CreateCommand(ParsedCommand));
							PrintDebug(ParsedCommand);
							logger.NewLogEntry(DoubleLogToScreen, ">>> The server has replied: <<<" + '\n' + ServerReply, logFile);
							out.println(ServerReply+"\n\n");
							SessionHandler.disconnect();
							Client.close();
							input = "";
							ClearParsedCommand(ParsedCommand);
						}
						catch (Exception e)
						{
							e.printStackTrace();
						}
					}
					if (ParsedCommand[1].contentEquals("SetPortReset"))
					{
						try
						{
							ServerReply = SessionHandler.AdvancedSendCommandSequence("3528", "SetPortReset", E3528.CreateCommand(ParsedCommand));
							PrintDebug(ParsedCommand);
							logger.NewLogEntry(DoubleLogToScreen, ">>> The server has replied: <<<" + '\n' + ServerReply, logFile);
							out.println(ServerReply+"\n\n");
							SessionHandler.disconnect();
							Client.close();
							input = "";
							ClearParsedCommand(ParsedCommand);
						}
						catch (Exception e)
						{
							e.printStackTrace();
						}
					}
				}
			else
			{
				logger.NewLogEntry(DoubleLogToScreen, "Shit happens...\n\n", logFile);
				SessionHandler.disconnect();
				Client.close();
				input = "";
				ClearParsedCommand(ParsedCommand);
			}
		}
			
//End First Launch ============================//

			//Client.close();
		}
		} catch (IOException e)
		{
			logger.NewLogEntry(DoubleLogToScreen, "The connection went wrong: device is unavailable or busy or has non-standart login-password pair.\n\n", logFile);
			out.close();
			in.close();
			Client.close();
		};
		
//=========================== End Socket Operating =======================================//


/*/---------------------------- Telnet operating ------------------------------------------//
		if (SessionHandler.ServerConnect("10.56.65.5"))
		{
			ServerReply = SessionHandler.sendCommand("display adsl port state 0/0/2");
			System.out.println();
			System.out.println("The server has replied:\n" + ServerReply);
			SessionHandler.disconnect();
		}
	}

//=========================== End Telnet Operating ======================================/*/	

/*/ ------------------------- Testing CommandParser -------------------------------------//
	
	String Command1 = "Command: GetPortStatus\nLine: 10.56.156.1:500";
	String Command2 = "Command: SetPortReset\nLine: 10.56.64.11:0/6/13";
	String Command3 = "Command: SetPortRateProfile\nLine: 10.56.0.187:0/13/13\nIDRateProfile: 2";
	
	ParsedCommand = CP.ParseInputFromSocket(Command2);
	System.out.println("The source command is: " + Command2);
	System.out.println();
	
	System.out.println("Command:" + ParsedCommand[0]);
	System.out.println("IP:" + ParsedCommand[1]);
	System.out.println("Port:" + ParsedCommand[2]);
	System.out.println("IDRateProfile:" + ParsedCommand[3]);
	System.out.println();
	
	System.out.println(MA5600.CreateCommand(ParsedCommand));
	
// ========================= End testing CommandParser =====================================/*/
	
		
		}
	}
}


// telnet programming http://sadun-util.sourceforge.net/telnet_library.html